package org.blog.util.encode;

import java.security.MessageDigest;

public class CreateKey {

	/**
	 * 加密算法
	 * 
	 * @param password
	 * @param randKey
	 * @param key
	 * @return
	 */
	public static String getEncryptPwd(String password, String randKey,
			String key) {

		String p[] = getArrayString(password, 16);
		int size = p.length;
		String retStr = "";
		byte[][] b = new byte[size][];
		for (int i = 0; i < size; i++) {
			if (i == 0) {
				b[i] = getXOR(
						p[i].getBytes(),
						getXORKey(byteArrayCopy(key.getBytes(),
								randKey.getBytes())));
			} else {
				b[i] = getXOR(p[i].getBytes(),
						getXORKey(byteArrayCopy(key.getBytes(), b[i - 1])));
			}
		}
		for (int i = 0; i < size; i++) {
			retStr += toHexString(b[i]);
		}
		return retStr.toUpperCase();
	}

	/**
	 * 解密算法
	 * 
	 * @param password
	 * @param randKey
	 * @param key
	 * @return
	 */
	public static String getUnEncryptPwd(String password, String randKey,
			String key) {
		byte[] pwd = new byte[password.length() / 2];
		for (int i = 0; i < pwd.length; ++i) {
			pwd[i] = HEXbyte(password.substring(i * 2, i * 2 + 2));
		}
		int size = pwd.length / 16;
		if (pwd.length % 16 != 0)
			++size;
		byte[][] b = new byte[size][];
		for (int i = 0; i < size; ++i) {
			int tmp = i * 16 + 16;
			if (pwd.length - tmp >= 0)
				b[i] = new byte[16];
			else {
				b[i] = new byte[pwd.length + 16 - tmp];
			}
			for (int j = 0; j < b[i].length; ++j) {
				b[i][j] = pwd[(i * 16 + j)];
			}
		}

		for (int i = size - 1; i >= 0; --i) {
			if (i == 0)
				b[i] = CreateKey.getXOR(
						b[i],
						CreateKey.getXORKey(CreateKey.byteArrayCopy(
								key.getBytes(), randKey.getBytes())));
			else {
				b[i] = CreateKey.getXOR(
						b[i],
						CreateKey.getXORKey(CreateKey.byteArrayCopy(
								key.getBytes(), b[(i - 1)])));
			}
		}

		String retStr = "";
		for (int i = 0; i < size; ++i) {
			retStr = retStr + new String(b[i]);
		}
		return retStr;
	}

	private static byte[] byteArrayCopy(byte[] b1, byte[] b2) {
		byte b[] = new byte[b1.length + b2.length];
		int j = 0;
		for (int i = 0; i < b1.length; i++, j++) {
			b[j] = (byte) b1[i];
		}
		for (int i = 0; i < b2.length; i++, j++) {
			b[j] = (byte) b2[i];
		}
		return b;
	}

	private static String[] getArrayString(String str, int len) {
		int size = (str.length() / len);
		if (0 != str.length() % len)
			size++;
		String p[] = new String[size];
		for (int i = 0; i < size; i++) {
			if (i == size - 1) {
				p[i] = str.substring(i * 16);
			} else
				p[i] = str.substring(i * 16, i * 16 + 16);
		}
		return p;
	}

	private static byte[] formatByte(byte[] str) {
		if (16 > str.length) {
			byte[] b = new byte[16];
			int i;
			for (i = 0; i < str.length; i++) {
				b[i] = str[i];
			}
			for (; i < b.length; i++) {
				b[i] = 0;
			}
			return b;
		} else
			return str;
	}

	private static byte[] byteXOR(byte[] a, byte[] b, int star, int len) {
		if (a == null) {
			a = new byte[len];
			for (int i = 0; i < len; i++) {
				a[i] = b[i];
			}
			star = len;
		}
		int i, j;
		for (i = star, j = 0; i < b.length; i++) {
			a[j] = (byte) (a[j] ^ (byte) b[i]);
			j++;
			if (j == len)
				break;
		}
		if (i >= b.length) {
			return a;
		} else
			return byteXOR(a, b, star + len, len);
	}

	private static byte[] getXORKey(byte[] p) {
		if (p.length <= 16) {
			return formatByte(p);
		} else {
			return byteXOR(null, p, 0, 16);
		}
	}

	private static byte[] getXOR(byte[] aByte, byte[] bByte) {
		byte[] c = new byte[aByte.length];
		for (int i = 0; i < aByte.length; i++) {
			c[i] = (byte) (aByte[i] ^ bByte[i]);
		}
		return c;
	}

	private static String toHexString(byte str[]) {
		StringBuffer buf = new StringBuffer(str.length * 2);
		for (int i = 0; i < str.length; i++) {
			buf.append(byteHEX(str[i]));
		}
		return buf.toString();
	}

	private static String byteHEX(byte ib) {
		char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A',
				'B', 'C', 'D', 'E', 'F' };
		char[] ob = new char[2];
		ob[0] = Digit[(ib >>> 4) & 0X0F];
		ob[1] = Digit[ib & 0X0F];
		String s = new String(ob);
		return s;
	}

	private static byte HEXbyte(String hex) {
		return (byte) (Integer.parseInt("" + hex.charAt(0), 16) << 4 | Integer
				.parseInt("" + hex.charAt(1), 16));
	}

	private final static String charsert = "UTF-8";

	public static String getMD5ofStr(String str) {
		try {
			MessageDigest messageDigest = MessageDigest.getInstance("MD5");

			messageDigest.reset();

			messageDigest.update(str.getBytes(charsert));

			byte[] byteArray = messageDigest.digest();

			StringBuilder md5StrBuff = new StringBuilder();

			for (int i = 0; i < byteArray.length; ++i) {
				if (Integer.toHexString(0xFF & byteArray[i]).length() == 1) {
					md5StrBuff.append("0").append(
							Integer.toHexString(0xFF & byteArray[i]));
				} else {
					md5StrBuff.append(Integer.toHexString(0xFF & byteArray[i]));
				}
			}

			return md5StrBuff.toString().toUpperCase();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

}
